package org.xs.web.http.velocity;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;

import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.io.VelocityWriter;
import org.xs.web.http.XSRules;
import org.xs.web.http.exception.LayoutTemplateNotFound;
import org.xs.web.http.exception.TemplateNotFound;
import org.xs.web.util.Helpers;


public class LayoutFactory {
	
	public static String layout(VelocityEngine ve,String templateName,Map coreContext){
		Template selfTmplate = getTemplate(ve,templateName);
		Template layoutTemplate = layoutTemplate(ve, templateName);
		String templateAsS = getTemplateAsString(new ChainedContext(coreContext),selfTmplate);
		String all = getTemplateAsString(new LayoutContext(coreContext,templateAsS), layoutTemplate);
		return all;
	} 
	
	public static Template layoutTemplate(VelocityEngine ve,String templateName){
		String[] rootAndName = templateName.split("/");
		String root = rootAndName[0],name = rootAndName[1];
		String _root = "_"+root,_name = "_"+name;
		String rootPath = root+"/"+_root + XSRules.templateDot(), namePath = root+"/"+_name;
		Object[] paths = Helpers.arrayMerge(new String[]{namePath,rootPath}, XSRules.defaultLayout);
		Template temp = null;
		for(Object path : paths){
			temp = getTemplateAndWrap(ve, (String)path);
			if(temp != null){
				return temp;
			} 
		}
	
		throw new LayoutTemplateNotFound(templateName);
	}
	 
	
	public static String getTemplateAsString(Context context,Template template){
		StringWriter swrite = new StringWriter();
		VelocityWriter vw = new VelocityWriter(swrite, 4 *1024, true);
		try {
			template.merge(context, vw);
			vw.flush();
			return swrite.toString();
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}finally{
			try {
				vw.close();
			} catch (IOException e) {
			}
		}
	}
	
	public static Template getTemplateAndWrap(VelocityEngine ve, String layoutName) {
	    try {
				return  getTemplate(ve,layoutName);
		    } 	catch (Exception e) { 
		    }
		return null;
	}
	public static Template getTemplate(VelocityEngine ve,String name){
			 
				try {
					return ve.getTemplate(name, XSRules.Encode);
				} catch (ResourceNotFoundException e) {
					throw new TemplateNotFound(name);
				} catch (ParseErrorException e) {
					throw e;
				} catch (Exception e) {
					throw new TemplateNotFound(name);
				}
			   
	}

}
